# Copyright (c) 2019-2021 Manfred Moitzi
# License: MIT License
from typing import TYPE_CHECKING
import copy
from ezdxf.math import Vec3
from ezdxf.lldxf.attributes import (
    DXFAttr,
    DXFAttributes,
    DefSubclass,
    XType,
    group_code_mapping,
)
from ezdxf.lldxf.const import SUBCLASS_MARKER, DXF2007
from .dxfentity import base_class, SubclassProcessor, DXFEntity
from .dxfgfx import DXFGraphic, acdb_entity
from .dxfobj import DXFObject
from .objectcollection import ObjectCollection

if TYPE_CHECKING:
    from ezdxf.eztypes import TagWriter, DXFNamespace, Tags, Drawing

__all__ = ["ACADTable"]

acdb_block_reference = DefSubclass(
    "AcDbBlockReference",
    {
        "geometry": DXFAttr(2),
        # Block name; an anonymous block begins with a *T value
        "insert": DXFAttr(10, xtype=XType.point3d, default=Vec3(0, 0, 0)),
        # Insertion point
    },
)
acdb_block_reference_group_codes = group_code_mapping(acdb_block_reference)

acdb_table = DefSubclass(
    "AcDbTable",
    {
        "version": DXFAttr(280),  # Table data version number: 0 = 2010
        "table_style_id": DXFAttr(
            342
        ),  # Hard pointer ID of the TABLESTYLE object
        "block_record": DXFAttr(
            343
        ),  # Hard pointer ID of the owning BLOCK record
        "horizontal_direction": DXFAttr(11),  # Horizontal direction vector
        "table_value": DXFAttr(90),  # Flag for table value (unsigned integer)
        "n_rows": DXFAttr(91),  # Number of rows
        "n_cols": DXFAttr(92),  # Number of columns
        "override_flag": DXFAttr(93),  # Flag for an override
        "border_color_override_flag": DXFAttr(94),
        # Flag for an override of border color
        "border_lineweight_override_flag": DXFAttr(95),
        # Flag for an override of border lineweight
        "border_visibility_override_flag": DXFAttr(96),
        # Flag for an override of border visibility
        # 141: Row height; this value is repeated, 1 value per row
        # 142: Column height; this value is repeated, 1 value per column
        # for every cell:
        #      171: Cell type; this value is repeated, 1 value per cell:
        #           1 = text type
        #           2 = block type
        #      172: Cell flag value; this value is repeated, 1 value per cell
        #      173: Cell merged value; this value is repeated, 1 value per cell
        #      174: Boolean flag indicating if the autofit option is set for the cell; this value is repeated, 1 value per cell
        #      175: Cell border width (applicable only for merged cells); this value is repeated, 1 value per cell
        #      176: Cell border height (applicable for merged cells); this value is repeated, 1 value per cell
        #       91: Cell override flag; this value is repeated, 1 value per cell (from AutoCAD 2007)
        #      178: Flag value for a virtual edge
        #      145: Rotation value (real; applicable for a block-type cell and a text-type cell)
        #      344: Hard pointer ID of the FIELD object. This applies only to a text-type cell. If the text in the cell
        #           contains one or more fields, only the ID of the FIELD object is saved. The text string
        #           (group codes 1 and 3) is ignored
        #        1: Text string in a cell. If the string is shorter than 250 characters, all characters appear in code 1.
        #           If the string is longer than 250 characters, it is divided into chunks of 250 characters. The chunks are
        #           contained in one or more code 2 codes. If code 2 codes are used, the last group is a code 1 and is
        #           shorter than 250 characters. This value applies only to text-type cells and is repeated, 1 value per cell
        #        2: Text string in a cell, in 250-character chunks; optional. This value applies only to text-type cells and
        #           is repeated, 1 value per cell
        #      340: Hard-pointer ID of the block table record. This value applies only to block-type cells and is repeated,
        #           1 value per cell
        #      144: Block scale (real). This value applies only to block-type cells and is repeated, 1 value per cell
        #      176: Number of attribute definitions in the block table record (applicable only to a block-type cell)
        #      for every ATTDEF:
        #           331: Soft pointer ID of the attribute definition in the block table record, referenced by group code 179
        #                (applicable only for a block-type cell). This value is repeated once per attribute definition
        #           300: Text string value for an attribute definition, repeated once per attribute definition and applicable
        #                only for a block-type cell
        #        7: Text style name (string); override applied at the cell level
        #      140: Text height value; override applied at the cell level
        #      170: Cell alignment value; override applied at the cell level
        #       64: Value for the color of cell content; override applied at the cell level
        #       63: Value for the background (fill) color of cell content; override applied at the cell level
        #       69: True color value for the top border of the cell; override applied at the cell level
        #       65: True color value for the right border of the cell; override applied at the cell level
        #       66: True color value for the bottom border of the cell; override applied at the cell level
        #       68: True color value for the left border of the cell; override applied at the cell level
        #      279: Lineweight for the top border of the cell; override applied at the cell level
        #      275: Lineweight for the right border of the cell; override applied at the cell level
        #      276: Lineweight for the bottom border of the cell; override applied at the cell level
        #      278: Lineweight for the left border of the cell; override applied at the cell level
        #      283: Boolean flag for whether the fill color is on; override applied at the cell level
        #      289: Boolean flag for the visibility of the top border of the cell; override applied at the cell level
        #      285: Boolean flag for the visibility of the right border of the cell; override applied at the cell level
        #      286: Boolean flag for the visibility of the bottom border of the cell; override applied at the cell level
        #      288: Boolean flag for the visibility of the left border of the cell; override applied at the cell level
        #       70: Flow direction; override applied at the table entity level
        #       40: Horizontal cell margin; override applied at the table entity level
        #       41: Vertical cell margin; override applied at the table entity level
        #      280: Flag for whether the title is suppressed; override applied at the table entity level
        #      281: Flag for whether the header row is suppressed; override applied at the table entity level
        #        7: Text style name (string); override applied at the table entity level. There may be one entry for each cell type
        #      140: Text height (real); override applied at the table entity level. There may be one entry for each cell type
        #      170: Cell alignment (integer); override applied at the table entity level. There may be one entry for each cell type
        #       63: Color value for cell background or for the vertical, left border of the table; override applied at the
        #           table entity level. There may be one entry for each cell type
        #       64: Color value for cell content or for the horizontal, top border of the table; override applied at the
        #           table entity level. There may be one entry for each cell type
        #       65: Color value for the horizontal, inside border lines; override applied at the table entity level
        #       66: Color value for the horizontal, bottom border lines; override applied at the table entity level
        #       68: Color value for the vertical, inside border lines; override applied at the table entity level
        #       69: Color value for the vertical, right border lines; override applied at the table entity level
        #      283: Flag for whether background color is enabled (default = 0); override applied at the table entity level.
        #           There may be one entry for each cell type: 0/1 = Disabled/Enabled
        #      274-279: Lineweight for each border type of the cell (default = kLnWtByBlock); override applied at the table
        #               entity level. There may be one group for each cell type
        #      284-289: Flag for visibility of each border type of the cell (default = 1); override applied at the table
        #               entity level. There may be one group for each cell type: 0/1 = Invisible/Visible
        #  97: Standard/title/header row data type
        #  98: Standard/title/header row unit type
        #   4: Standard/title/header row format string
        #
        # AutoCAD 2007 and before:
        # 177: Cell override flag value (before AutoCAD 2007)
        #  92: Extended cell flags (from AutoCAD 2007), COLLISION: group code also used by n_cols
        # 301: Text string in a cell. If the string is shorter than 250 characters, all characters appear in code 302. If
        #      the string is longer than 250 characters, it is divided into chunks of 250 characters. The chunks are
        #      contained in one or more code 303 codes. If code 393 codes are used, the last group is a code 1 and is
        #      shorter than 250 characters. This value applies only to text-type cells and is repeated,
        #      1 value per cell (from AutoCAD 2007)
        # 302: Text string in a cell, in 250-character chunks; optional. This value applies only to text-type cells and is
        #      repeated, 302 value per cell (from AutoCAD 2007)
        #
        # REMARK from Autodesk:
        # Group code 178 is a flag value for a virtual edge. A virtual edge is used when a grid line is shared by two cells.
        # For example, if a table contains one row and two columns and it contains cell A and cell B, the central grid line
        # contains the right edge of cell A and the left edge of cell B. One edge is real, and the other edge is virtual.
        # The virtual edge points to the real edge; both edges have the same set of properties, including color, lineweight,
        # and visibility.
    },
)
acdb_table_group_codes = group_code_mapping(acdb_table)


# todo: implement ACAD_TABLE
class ACADTable(DXFGraphic):
    """DXF ACAD_TABLE entity"""

    DXFTYPE = "ACAD_TABLE"
    DXFATTRIBS = DXFAttributes(
        base_class, acdb_entity, acdb_block_reference, acdb_table
    )
    MIN_DXF_VERSION_FOR_EXPORT = DXF2007

    def __init__(self):
        super().__init__()
        self.data = None

    def _copy_data(self, entity: "DXFEntity") -> None:
        """Copy data."""
        assert isinstance(entity, ACADTable)
        entity.data = copy.deepcopy(self.data)

    def load_dxf_attribs(
        self, processor: SubclassProcessor = None
    ) -> "DXFNamespace":
        dxf = super().load_dxf_attribs(processor)
        if processor:
            processor.fast_load_dxfattribs(
                dxf, acdb_block_reference_group_codes, subclass=2
            )
            tags = processor.fast_load_dxfattribs(
                dxf, acdb_table_group_codes, subclass=3, log=False
            )
            self.load_table(tags)
        return dxf

    def load_table(self, tags: "Tags"):
        pass

    def export_entity(self, tagwriter: "TagWriter") -> None:
        """Export entity specific data as DXF tags."""
        super().export_entity(tagwriter)
        tagwriter.write_tag2(SUBCLASS_MARKER, acdb_block_reference.name)
        self.dxf.export_dxf_attribs(tagwriter, ["geometry", "insert"])
        tagwriter.write_tag2(SUBCLASS_MARKER, acdb_table.name)
        self.export_table(tagwriter)

    def export_table(self, tagwriter: "TagWriter"):
        pass


acdb_table_style = DefSubclass(
    "AcDbTableStyle",
    {
        "version": DXFAttr(280),  # 0 = 2010
        "name": DXFAttr(3),
        # Table style description (string; 255 characters maximum)
        "flow_direction": DXFAttr(7),  # FlowDirection (integer):
        # 0 = Down
        # 1 = Up
        "flags": DXFAttr(7),  # Flags (bit-coded)
        "horizontal_cell_margin": DXFAttr(40),
        # Horizontal cell margin (real; default = 0.06)
        "vertical_cell_margin": DXFAttr(41),
        # Vertical cell margin (real; default = 0.06)
        "suppress_title": DXFAttr(280),
        # Flag for whether the title is suppressed: 0/1 = not suppressed/suppressed
        "suppress_column_header": DXFAttr(281),
        # Flag for whether the column heading is suppressed: 0/1 = not suppressed/suppressed
        # The following group codes are repeated for every cell in the table
        #   7: Text style name (string; default = STANDARD)
        # 140: Text height (real)
        # 170: Cell alignment (integer)
        #  62: Text color (integer; default = BYBLOCK)
        #  63: Cell fill color (integer; default = 7)
        # 283: Flag for whether background color is enabled (default = 0): 0/1 = disabled/enabled
        #  90: Cell data type
        #  91: Cell unit type
        # 274-279: Lineweight associated with each border type of the cell (default = kLnWtByBlock)
        # 284-289: Flag for visibility associated with each border type of the cell (default = 1): 0/1 = Invisible/Visible
        # 64-69: Color value associated with each border type of the cell (default = BYBLOCK)
    },
)


# todo: implement TABLESTYLE
class TableStyle(DXFObject):
    """DXF TABLESTYLE entity

    Every ACAD_TABLE has its own table style.

    Requires DXF version AC1021/R2007
    """

    DXFTYPE = "TABLESTYLE"
    DXFATTRIBS = DXFAttributes(base_class, acdb_table_style)
    MIN_DXF_VERSION_FOR_EXPORT = DXF2007


class TableStyleManager(ObjectCollection):
    def __init__(self, doc: "Drawing"):
        super().__init__(
            doc, dict_name="ACAD_TABLESTYLE", object_type="TABLESTYLE"
        )
